<?php

namespace App\Http\Controllers;

use DB;
use Cache;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

use EasyWeChat\Foundation\Application;

use App\Http\Models\Captcha;
use App\Http\Models\Object;
use App\Http\Models\Order;
use App\Http\Models\Price;
use App\Http\Models\Line;
use App\Http\Models\User;
use App\Http\Models\Record;
use App\Http\Models\PayRequest;
use App\Http\Models\VisualTotal;
use App\Http\Models\VisualData;
use App\Http\Controllers\Pay\Request as OnlinePayRequest;

class ApiController extends Controller
{

    protected function insertLineItem($period, $object, $objectPrice, $objectPriceTime)
    {

        //周期开始第一次存储
        if (Line::where('id_object', $object->id)->where('body_period', $period)->where('created_at', '>=', date('Y-m-d H:i:s', time() - $period))->count() == 0) {

            $line = new Line;
            $line->id_object = $object->id;
            $line->body_period = $period;
            $line->body_open = sprintf('%.' . $object->body_price_decimal . 'f', $objectPrice);
            $line->body_high = $line->body_open;
            $line->body_low = $line->body_open;
            $line->body_close = $line->body_open;
            $line->body_volume = 0;



            //计算5均线 10均线 15均线 查找前15数据 应该是14 最后一个是目前这个
            $beforeData = Line::where('id_object',$object->id)->where('body_period',$period)->orderBy('created_at','desc')->paginate(14);
            $tmpTotal = 0;
            foreach($beforeData as $key => $val){

                $tmpTotal += floatval($val['body_open']);//采用开盘价的来计算 就不需要在每次更新的时候 计算了 减少了很多计算量
                if($key == 3){
                    //$total5 = $tmpTotal + floatval($line->body_close);//要加上目前的
                    $line->body_five = sprintf("%.5f",($tmpTotal + floatval($line->body_open))/5);
                }
                if($key == 8){
                    //$total10 = $tmpTotal + floatval($line->body_close);
                    $line->body_ten = sprintf("%.5f",($tmpTotal + floatval($line->body_open))/10);
                }
                if($key == 13){
                    //$total15 = $tmpTotal + floatval($line->body_close);
                    $line->body_fifteen = sprintf("%.5f",($tmpTotal + floatval($line->body_open))/15);
                }
            }
            //如果数量不够  比如计算不出body_fifteen 就用 body_ten的数据
            if(!isset($line->body_five)){
                $line->body_five = $line->body_open;
            }
            if(!isset($line->body_ten)){
                $line->body_ten = $line->body_five;
            }
            if(!isset($line->body_fifteen)){
                $line->body_fifteen = $line->body_ten;
            }



            if (intval($line->body_open) && intval($line->body_high) && intval($line->body_low) && intval($line->body_close)) {
                $line->save();
            }
            Line::where('id_object', $object->id)->where('body_period', $period)->where('created_at', '<', date('Y-m-d H:i:s', strtotime($objectPriceTime) - $period * 60))->delete();
        } else {
            //更新该周期的数据
            $line = Line::where('id_object', $object->id)->where('body_period', $period)->where('created_at', '>=', date('Y-m-d H:i:s', time() - $period))->first();
            $line_closed_at = strtotime($line->created_at) + $line->body_period;
            if (time() < $line_closed_at) {

                if ($objectPrice > $line->body_high) {
                    $line->body_high = sprintf('%.' . $object->body_price_decimal . 'f', $objectPrice);
                }
                if ($objectPrice < $line->body_low) {
                    $line->body_low = sprintf('%.' . $object->body_price_decimal . 'f', $objectPrice);
                }
                $line->body_close = sprintf('%.' . $object->body_price_decimal . 'f', $objectPrice);
                $line->body_volume = $line->body_volume + mt_rand(0, 1);
                if (intval($line->body_open) && intval($line->body_high) && intval($line->body_low) && intval($line->body_close)) {
                    $line->save();
                }
            }
        }
    }

    protected function insertLine($object, $objectPrice, $objectPriceTime)
    {

        if ($object->body_status == 1) {
            $this->insertLineItem(60, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(300, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(900, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(1800, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(3600, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(86400, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(604800, $object, $objectPrice, $objectPriceTime);
            $this->insertLineItem(2592000, $object, $objectPrice, $objectPriceTime);
        }

    }

    protected function insertPrice($object, $objectPrice, $objectPriceTime, $objectPriceMin, $objectPriceMax, $objectPriceInterval)
    {

        //当前时间的价格没有
        $time = time();
        if (Price::where('id_object', $object->id)->where('body_price_time', date('Y-m-d H:i:s', $time))->count() == 0) {
            if (Price::where('id_object', $object->id)->where('body_price_time', $objectPriceTime)->count() == 0) {

                if (floatval($object->body_price) == floatval($objectPrice)) {
                    $object->body_price_repeat = intval($object->body_price_repeat) + 1;
                    if ($object->body_price_repeat >= 180) {
                        $object->body_status = 0;
                    }
                } else {

                    $object->body_price_repeat = 0;
                    $object->body_status = 1;

                    $price = new Price;
                    $price->id_object = $object->id;
                    $price->body_price = sprintf('%.' . $object->body_price_decimal . 'f', $objectPrice);
                    $price->body_price_time = $objectPriceTime;
                    $price->save();

                    $object->body_price_previous = $object->body_price;
                    $object->body_price = $price->body_price;
                    $object->body_price_min = $objectPriceMin;
                    $object->body_price_max = $objectPriceMax;
                    $object->body_price_interval = $objectPriceInterval;
                    $object->save();

                    Price::where('id_object', $object->id)->where('body_price_time', '<', date('Y-m-d H:i:s', strtotime($price->body_price_time) - 6400))->delete();

                }


            }
        } else {
            //如果当前的价格有了 就用当前的价格 这里就是生产出来的假数据
            $price = Price::where('id_object', $object->id)->where('body_price_time', date('Y-m-d H:i:s', $time))->first();
            $object->body_price_previous = $object->body_price;
            $object->body_price = $price->body_price;
            $object->save();
        }

        $objectPrice = $object->body_price;

        $this->insertLine($object, $objectPrice, $objectPriceTime);

    }

    public function fetch()
    {

        $requestResults = shell_exec("curl -s http://market.forex.com.cn/zhongfuMarketIndex/findAllPriceAjax.do?" . mt_rand(100000000, 999999999));
        //$requestResults = file_get_contents("http://market.forex.com.cn/zhongfuMarketIndex/findAllPriceAjax.do?" . mt_rand(100000000, 999999999));
        if (!Cache::has(md5($requestResults))) {
            Cache::put(md5($requestResults), 'FETCHED', 4320);
            $requestResults = json_decode($requestResults, TRUE);

            $objects = Object::all();
            foreach ($objects as $item) {
                $this->insertPrice($item, $requestResults[$item->body_tag_forex]['sellPrice'], date('Y-m-d H:i:s', time()), $requestResults[$item->body_tag_forex]['sellPrice'], $requestResults[$item->body_tag_forex]['sellPrice'], 0);
            }
        }


        /*
        $requestResults = json_decode(file_get_contents('http://market.forex.com.cn/zhongfuMarketIndex/ajaxTable.do?' . mt_rand(100000000, 999999999)), TRUE);
        $responseLists = $requestResults['list'];
        $responseArray = array();

        foreach ($responseLists as $item) {
            $responseArray[$item['symbolCode']] = $item;
        }

        //die(print_r($responseArray['GBPJPY']));

        */


        echo('FETCH_DONE');

        /*
        $requestResults = json_decode(file_get_contents('http://market.forex.com.cn/zhongfuMarketIndex/ajaxTable.do?' . mt_rand(100000000, 999999999)), TRUE);
        $responseLists = $requestResults['list'];
        $responseArray = array();

        foreach ($responseLists as $item) {
            $responseArray[$item['symbolCode']] = $item;
        }
        
        $objects = Object::all();
        foreach ($objects as $item) {
            $this->insertPrice($item, $responseArray[$item->body_tag_forex]['sellPrice'], date('Y-m-d H:i:s', time()), $responseArray[$item->body_tag_forex]['sellPrice'], $responseArray[$item->body_tag_forex]['sellPrice'], 0);
        }
        */

        /*

        $requestString = 'http://hq.sinajs.cn/list=';
        $objects = Object::all();
        foreach($objects as $object) $requestString = $requestString . ',' .$object->body_tag;
        $requestString = str_replace('list=,', 'list=', $requestString);
	    $requestResults = explode(';', file_get_contents($requestString));
	    foreach ($requestResults as $item) {
            if(strstr($item, '=')){
		        $arrayForName = explode('=', $item);
		        $arrayForObject = explode(',', $arrayForName[1]);
		        $objectName = trim(str_replace('var hq_str_', '', $arrayForName[0]));
		        if($objectName && $object = Object::where('body_tag', $objectName)->first()){
                    if ($objectName == 'sh000010'
                    || $objectName == 'sh000300') {
                        $objectPrice = str_replace('"', '', $arrayForObject[3]);
                        $objectPriceTime = $arrayForObject[30] . ' ' . $arrayForObject[31];
                        $objectPriceMin = $arrayForObject[4];
                        $objectPriceMax = $arrayForObject[5];
                        $objectPriceInterval = $arrayForObject[6];
                    } else if ($objectName == 'rt_hkHSI') {
                        $objectPrice = str_replace('"', '', $arrayForObject[6]);
                        $objectPriceTime = str_replace('/', '-', $arrayForObject[17]) . ' ' . str_replace('"', '', $arrayForObject[18]);
                        $objectPriceMin = $arrayForObject[5];
                        $objectPriceMax = $arrayForObject[4];
                        $objectPriceInterval = 0;
                    } else if ($objectName == 'gb_$ndx'
                    || $objectName == 'gb_$dji'
                    || $objectName == 'gb_bidu'
                    || $objectName == 'gb_baba'
                    || $objectName == 'gb_jd') {
                        $objectPrice = str_replace('"', '', $arrayForObject[1]);
                        $objectPriceTime = $arrayForObject[3];
                        $objectPriceMin = $arrayForObject[6];
                        $objectPriceMax = $arrayForObject[7];
                        $objectPriceInterval = 0;
                    } else if ($objectName == 'hf_CL'
                    || $objectName == 'hf_GC'
                    || $objectName == 'hf_SI') {
                        $objectPrice = str_replace('"', '', $arrayForObject[0]);
                        $objectPriceTime = $arrayForObject[12] . ' ' . $arrayForObject[6];
                        $objectPriceMin = $arrayForObject[5];
                        $objectPriceMax = $arrayForObject[4];
                        $objectPriceInterval = $arrayForObject[1];
                    } else {
                        $objectPrice = $arrayForObject[1];
                        $objectPriceTime = str_replace('"', '', $arrayForObject[17]) . ' ' . str_replace('"', '', $arrayForObject[0]);
                        $objectPriceMin = $arrayForObject[7];
                        $objectPriceMax = $arrayForObject[6];
                        $objectPriceInterval = $arrayForObject[11];
                    }
                    $this->insertPrice($object, $objectPrice, $objectPriceTime, $objectPriceMin, $objectPriceMax, $objectPriceInterval);
		        }
            }
	    }

        */
    }



    //计算输和赢的
    //这玩意是不是应该定时计算
    public function compute()
    {
        //找到没有计算的订单
        $orders = Order::where('striked_at', '0000-00-00 00:00:00')->get();

        foreach ($orders as $order) {
            //body_time 买的区间
            //从订单的创建时间 +   那就是说任何时候下订单 那么那个line的区间干嘛用呢 line的区间是k线的区间
            //结算的时间
            $order_striked_time = strtotime($order->created_at) + $order->body_time;
            //说明已经可以计算了 不符合条件的就直接跳过 等到条件符合后再计算
            if ($order_striked_time <= time()) {

                //这个判断是起什么作用呢
                //对了 就是没有调控的 才从真实的数据中取数据 如果是调控的 那么结算时候的价格早就在订单之中了  但是这个怎么样反应到K线中 不然的话 会看出来 这个地方就是关键
                if ($order->body_is_controlled == 0) {//这个订单是否调控 是在下订单的时候 就已经从配置当中判断 是否是调控的订单了
                    //取出价格历史表中离判断盈亏时间最近的最新的那条
                    //object_latestPrice 的取出有个问题 就是如果世间过的太久了 数据库里当时的数据没有保存 所以可能取不出来数据 所以一定要开启这个计算
                    //对了 如果没有 那么可不可以造一条假的数据 不知道这调数据的id 会不会被其他的表引用  会不会影响其他
                    $object_latestPrice = Price::where('id_object', $order->id_object)->where('body_price_time', '<=', date('Y-m-d H:i:s', $order_striked_time))->orderBy('created_at', 'desc')->first();

                    //防止实在过期了 数据被删的异常 反正这里的数据是不被记录的
                    //这些数据会被删除，说并不是很重要，这只是一个用来判断当时输赢的数据，如果为了能够查证，那么把数据留的久一点就好了 保存的时间长些，其实也没啥，因为删除不删除 id依然是网上长的，只不过影响了查询的速度
                    //数据上，处理好用户余额与每次的输赢记录 能够对上这个就行了
                    if (!$object_latestPrice)

                        $object_latestPrice = Price::where('id_object', $order->id_object)->orderBy('created_at', 'desc')->first();
                    //取到最后的价格
                    $order->body_price_striked = $object_latestPrice->body_price;
                }

                //结算时间
                $order->striked_at = date('Y-m-d H:i:s', time());
                //下单时的价格 与 最后的价格相等  用户亏
                if (floatval($order->body_price_buying) == floatval($order->body_price_striked)) {
                    $order->body_is_win = 0;
                    $order->body_is_draw = 1;//is_draw = 1 代表平局
                    //下单时候的价格 小于最终的价格 direction 一定要搞懂 牵扯到很多  direction = 0 是看跌 一是看涨
                } else if (floatval($order->body_price_buying) < floatval($order->body_price_striked)) {
                    $order->body_is_win = $order->body_direction == 1 ? 1 : 0;
                    $order->body_is_draw = 0;
                } else {
                    $order->body_is_win = $order->body_direction == 0 ? 1 : 0;
                    $order->body_is_draw = 0;
                }
                $order->save();

                //盈利和平局在这里做记录  亏损的记录 因为在下订单的时候 默认记录的就是亏损的状态
                $user = User::where('id', $order->id_user)->first();
                //盈利的
                if ($order->body_is_win == 1) {
                    //加$order->body_stake 是把本金退回   然后再加上收益
                    $user->body_balance = $user->body_balance + $order->body_stake + $order->body_bonus;
                    $user->body_bonus = $user->body_bonus + $order->body_bonus;
                    $user->save();

                    $record = new Record;
                    $record->id_user = $user->id;
                    $record->id_order = $order->id;
                    $record->body_name = $order->body_direction == 1 ? '看涨盈利' : '看跌盈利';
                    $record->body_direction = 1;//盈和平局都是 direction= 1 因为平局要回退钱  默认原来是设置为0 的 如果没有赢和平局那就是 0 就是亏损
                    $record->body_stake = $order->body_stake + $order->body_bonus;   //本金加收益
                    $record->save();

                    //用户盈利 从代理商扣除一半
                    $introducer = User::where('id', $user->id_introducer)->first();
                    //代理商的余额应该要在用户下单的金额的一半以上 才能参与盈亏
                    $moneyShouldPay = floatval($order->body_stake / 2);
                    if ($introducer->introduce_num >= 50 && $introducer->body_balance >= $moneyShouldPay) {
                        $introducer->body_balance = $introducer->body_balance - $moneyShouldPay;
                        $introducer->save();

                        //记录代理的支出
                        $recordAgent = new Record;
                        $recordAgent->id_user = $introducer->id;
                        $recordAgent->id_refer = $user->id;
                        $recordAgent->body_name = '代理支出';
                        $recordAgent->body_direction = 0;
                        $recordAgent->body_stake = $moneyShouldPay;
                        $recordAgent->save();
                    }
                //平局
                } else if ($order->body_is_draw == 1) {

                    $user->body_balance = $user->body_balance + $order->body_stake;  
                    $user->save();

                    $record = new Record;
                    $record->id_user = $user->id;
                    $record->id_order = $order->id;
                    $record->body_name = $order->body_direction == 1 ? '看涨退回' : '看跌退回';
                    $record->body_direction = 1;
                    $record->body_stake = $order->body_stake;//这是把下定单的钱又回退回去了
                    $record->save();

                } else {
                    //用户亏损，代理商分得一半
                    $introducer = User::where('id', $user->id_introducer)->first();
                    //代理商的余额应该要在用户下单的金额的一半以上 才能参与盈亏
                    $moneyShouldPay = floatval($order->body_stake / 2);
                    if ($introducer->introduce_num >= 50 && $introducer->body_balance >= $moneyShouldPay) {
                        $introducer->body_balance = $introducer->body_balance + $order->body_stake;
                        $introducer->save();

                        //记录代理收入
                        $recordAgent = new Record;
                        $recordAgent->id_user = $introducer->id;
                        $recordAgent->id_refer = $user->id;
                        $recordAgent->body_name = '代理收入';
                        $recordAgent->body_direction = 0;
                        $recordAgent->body_stake = $moneyShouldPay;
                        $recordAgent->save();
                    }

                }

            }
        }

        echo('COMPUTE_DONE');

    }

    //将数字加或者剑法 margin 个最小单位
    protected function computeNumber($number, $direction, $margin)
    {
        //小数点十进制
        $numberExplode = explode('.', $number);
        //小数部分
        $numberDecimal = end($numberExplode);
        //小数部分长度
        $numberDecimalLength = strlen($numberDecimal);
        //假如长度为2 0.1的2次方 = 0.01
        $numberDecimalControl = pow(0.1, $numberDecimalLength);

        //直接在这里控制用户赢的概率
        $win = 0;
        $will_win_rate = env('ORDER_WILL_WIN');
        if((rand(0, 100) <= $will_win_rate)) {
            $win = 1;
        }

        if ($win) {
            if ($direction == 1) {
                //比如传进来number = 10.23  $margin = 2 那么计算公式就是  10.23 + 2 * 0.01 = 10.23 + 0.02 = 10.25
                return floatval($number) + $margin * $numberDecimalControl;
            } else {
                return floatval($number) - $margin * $numberDecimalControl;
            }
        } else {
            if ($direction == 1) {
                return floatval($number) - $margin * $numberDecimalControl;
            } else {
                return floatval($number) + $margin * $numberDecimalControl;
            }
        }

    }

//订单调控函数调用 目的是计算用户赢的比例
//这个函数只在调控的时候会调取到  目前是靠后台设置用户的输赢概率 所以这个暂时不需要了  先留在这里
    protected function computeRate($id)
    {
        //用户下单次数
        $orders_count = Order::where('id_user', $id)->count();
        if ($orders_count > 0) {
            //用户赢的次数
            $orders_is_win =Order::where('id_user', $id)->where('body_is_win', '1')->count();
            //赢的比例
            return ($orders_is_win / $orders_count) * 100;
        } else return 0;
    }

    /**
     * @param $time  判断盈亏的时间
     * @param $order
     * @param $object
     * @param $margin
     * @return mixed
     * 修改掉判断盈亏时间点上的那个数据
     */
    protected function computePriceItem($time, $order, $object, $margin)
    {

        $price = Price::firstOrNew(array(
            'id_object' => $order->id_object,
            'body_price_time' => date('Y-m-d H:i:s', $time),
            'created_at' => date('Y-m-d H:i:s', $time)
        ));

        //为什么是大于rank才修正，rank是起什么作用的
        if ($order->body_stake > $price->body_rank) {
            $price->body_price = $this->computeNumber(sprintf('%.' . $object->body_price_decimal . 'f', $order->body_price_buying), $order->body_direction, $margin);
            $price->body_rank = $order->body_stake;
            $price->save();
        }

        return $price;

    }

    //如果开启订单调控 那么在下单的时候会 处理这里
    protected function computePrice($user, $order, $object)
    {

        ////概率就是在这里计算  现在主要是控制k线的数据 概率控制换一下 在后台设置 100以上的赢的概率 200，500，1000以上赢的概率 分四个设置

        ////用户赢的比例 比如10次赢了1次 那么就是 1/10 * 100 = 10;
        ////这个函数只有这里调用到 暂时不用这个函数了
        ////$rate = $this->computeRate($user->id);
        //$rate = 0; //代表输的概率
        //$rate_100 = env('ORDER_WILL_LOST_PERCENT_100');
        //$rate_200 = env('ORDER_WILL_LOST_PERCENT_200');
        //$rate_500 = env('ORDER_WILL_LOST_PERCENT_500');
        //$rate_1000 = env('ORDER_WILL_LOST_PERCENT_1000');


        ////用这个比例基础 继续调整下
        //if (floatval($order->body_stake) < 100) {
            //$rate = 0;
       //     $rate = $rate_100;
        //} else {
        //    if (floatval($order->body_stake) >= 200)  $rate = $rate_200;//$rate = $rate + 10;
        //    if (floatval($order->body_stake) >= 500) $rate = $rate_500;//$rate = $rate + 10;
        //    if (floatval($order->body_stake) >= 1000) $rate = $rate_1000;//$rate = $rate + 15;
       // }

       // //强制亏损或者强制盈利 如果开启这个 就强制调控
       // /*if (env('ORDER_WILL_LOST') || env('ORDER_WILL_WIN')) {
        //    $rate = 100;
        //}*/

        //if (rand(0, 100) <= $rate) {

    //完全不需要上面那么复杂的计算 直接控制 ORDER_WILL_WIN  的概率就好了
            $order_striked_time = strtotime($order->created_at) + $order->body_time;
            $price = $this->computePriceItem($order_striked_time, $order, $object, mt_rand(1, 3));
            ////这一系列的连续 难道是为了修出一条平滑的曲线  如果有另外一个人同时买了这个时间怎么办
            ////不过好像也没事 只要计算了输赢，输赢是最终统一计算的
            ////这里没有修改K线上的数据 这修改了Price 表中的数据 用户是要看K线的
            ////所以只要提现在k线上就好了  这个问题应该是这样 在获取数据的时候 如果这里的数据有了 那么就用这里的数据 如果没有才是用网上的数据 即优先从Price中获取数据
            ////从lines中的 created_at 开始 k线周期时间之内的数据 都从Price调用

           // //K线上的那跟白色的横线 由于是从objects中调用的 ，所以会跟k线的块在 调控的时候显得不一致 所以那个数据不能从object中获取，而是应该从price表中获取
            $this->computePriceItem($order_striked_time - 4, $order, $object, 4);
            $this->computePriceItem($order_striked_time - 3, $order, $object, 3);
            $this->computePriceItem($order_striked_time - 2, $order, $object, 2);
            $this->computePriceItem($order_striked_time - 1, $order, $object, 1);
            $this->computePriceItem($order_striked_time + 1, $order, $object, 1);
            $this->computePriceItem($order_striked_time + 2, $order, $object, -1);

            $order->body_price_striked = $price->body_price; //先就计算出了结算的价格
            $order->body_is_controlled = 1;
            $order->save();

        //}

    }

    /*protected function computeNetwork($user, $order) {

        $introducerIndex = 0;
        while ($user->id_introducer != 0) {

            $introducerIndex++;
            $introducer = User::where('id', $user->id_introducer)->first();
            $introducer->body_transactions_network = $introducer->body_transactions_network + $order->body_stake;

            if($introducerIndex <= 3){

                $bonus = floatval($order->body_stake * floatval(env("AGENT_$introducerIndex")));
                if($bonus < 0.01) $bonus = 0.01;

                $introducer->body_balance = floatval($introducer->body_balance) + $bonus;

                $record = new Record;
                $record->id_user = $introducer->id;
                $record->id_refer = $user->id;
                $record->body_name = '推荐收入';
                $record->body_direction = 1;//1表示钱增加
                $record->body_stake = $bonus;
                $record->save();

            }

            $introducer->save();
            $user = $introducer;

        }
    }*/

    //只要计算一层的收益 只是一层分为了三个不同的等级 普通会员0-25 vip会员 25-50 代理商50
    protected function computeNetwork($user, $order)
    {

        $introducer = User::where('id', $user->id_introducer)->first();
        if (!$introducer) return;

        //记录下级的买入总额
        $introducer->body_transactions_network = $introducer->body_transactions_network + $order->body_stake;

        if ($introducer->introduce_num < 25) {
            //普通会员
            //bonus是收益
            $bonus = floatval($order->body_stake * floatval(env("MEMBER_1")));
        } else if ($introducer->introduce_num < 50) {
            //vip会员
            $bonus = floatval($order->body_stake * floatval(env("MEMBER_2")));
        } else {
            //代理商在判断盈亏的时候处理
            $introducer->save();
            return;
        }

        //收益累加到 余额
        $introducer->body_balance = floatval($introducer->body_balance) + $bonus;
        $introducer->save();

        $record = new Record;
        $record->id_user = $introducer->id;
        $record->id_refer = $user->id;
        $record->body_name = '推荐收入';
        $record->body_direction = 1;
        $record->body_stake = $bonus;
        $record->save();


    }


    public function automate()
    {

        $this->fetch();
        $this->compute();

        return response()->json([
            'result' => 'OK'
        ]);

    }

    public function objects()
    {

        $result = array(
            'timestamp' => time(),
            'objects' => array()
        );

        $objects = Object::where('is_disabled', '0')->orderBy('body_rank', 'desc')->get();
        $result['objects'] = $objects->toArray();

        if ($user = session('wechat.oauth_user')) {
            $user = User::where('id_wechat', $user->id)->first();
            $result['user'] = $user->toArray();
        }

        return response()->json($result);

    }




    /**
     * 制造假数据  假数据是在后台调用的 不应该是前台调用
     */
    public function businessData(){
        //获取最近更新的时间
        $visualData = VisualData::orderBy('created_at','desc')->first();
        if($visualData) {
            $lastTime = $visualData['created_at'];
        }else{
            $lastTime = date('Y-m-d H:i:s',time());
        }
        //将用户最新买的放入到假数据中
        $orders = Order::where('created_at','>',$lastTime)->orderBy('created_at','asc')->get();

        //标的物的数据
        $objects = Object::where("is_disabled","0")->get(['id','body_name','created_at']);
        $objectsArr = [];
        foreach($objects as $key => $val ){
            $objectsArr[$val->id] = ['body_name'=>$val->body_name,'created_at'=>$val['created_at']];
        }

        //真实的数据
        $result = [];
        foreach($orders as $key => $val ){
           array_push($result, ['object_name'=>$objectsArr[$val->id_object]['body_name'],'body_stake'=>$val->body_stake,'body_direction'=>$val->body_direction,
               'created_at'=>$objectsArr[$val->id_object]['created_at']]);
        }


        //生产虚拟数据
        $randNum = rand(0,2);
        $stakeList = [50,100,200,500,1000,2000,5000];
        $objectNum = count($objectsArr);
        $stakeListNum = count($stakeList);
        for($i = 0;$i< $randNum;$i++){
            $randObjectIndex = rand(0,$objectNum-1);
            $randDirection = rand(0,1);
            $randStakeIndex = rand(0,$stakeListNum-1);
            array_push($result,['object_name'=>$objects[$randObjectIndex]['body_name'],'body_stake'=>$stakeList[$randStakeIndex],'body_direction'=>$randDirection,
            'created_at'=>date('Y-m-d H:i:s',time())]);
        }

        foreach($result as $key => $val ){
            VisualData::insert($val);
        }

        //计算人数和总数  在产生的数据之上增加人数和总数
        $totalDataNum = count($result);
        $visualPeopleNum = rand(0,$totalDataNum);

        //取出当天的数据
        $todayTotal = VisualTotal::where('created_at','>',date('Y-m-d'))->first();
        //更新或者新增当天的数据
        if($todayTotal){
            $total = ['people'=>$todayTotal->people + $visualPeopleNum,'business_total'=>$todayTotal->business_total + $totalDataNum,'updated_at'=>date('Y-m-d H:i:s',time())];
            VisualTotal::where('id',$todayTotal->id)->update($total);
        }else{
            $total = ['people'=>$visualPeopleNum,'business_total'=>$totalDataNum,'created_at'=>date('Y-m-d H:i:s',time())];
            VisualTotal::insert($total);
        }

        return 'SUCCESS';
        //计算一下人数 和 总交易数

    }


    /**
     * 前端获取数据
     */
    public function getBusinessData(Request $request){
        $lastTime = $request->input('lastTime');
        //if(!$lastTime) return response()->json([]);
        if(!$lastTime) {
            $lastTime = 0;
        }
        //成交记录
        $visualData = VisualData::where('created_at','>',$lastTime)->orderBy('created_at','desc')->take(10)->get();//最多取5条
        $visualTotal = VisualTotal::where('created_at','>',date('Y-m-d',time()))->orderBy('created_at','desc')->first();
        if($visualData){
            $visualData = $visualData->toArray();
        }
        if($visualTotal){
            $visualTotal = $visualTotal->toArray();
        }
        return response()->json(['totalData'=>$visualTotal,'newData'=>$visualData]);
    }


    //兼容分时图

    public function objectsDetail(Request $request, Response $response, $id, $period)
    {
        $object = Object::find($id);
        //前端会用status判断是否休市
        if ($object->body_status == 1) {
            $object['status'] = TRUE;
        } else {
            $object['status'] = FALSE;
        }

        if($period == 1){
            //不能用id倒叙排 因为出现假数据的扰动的时候 会提前一段时间把数据存进来 导致分时图上的先有往回绕的现象  而且未来的数据不要出现
            //$prices = Price::where("id_object",$object->id)->orderBy('id','desc')->take(60)->get();
            $prices = Price::where("id_object",$object->id)->where("created_at","<=",date('Y-m-d H:i:s',time()))->orderBy('created_at','desc')->take(60)->get();
            $result = array(
                'timestamp' => time(),
                //'period' => $period,
                'object' => $object,
                'lines' => $prices->toArray()
            );
            return response()->json($result);
        }else{

            $lines = Line::where('id_object', $object->id)->where('body_period', $period)->orderBy('id', 'desc')->take(60)->get();



            //为什么要注释 看下面那个方法
            //$prices = Price::where("id_object",$id)->where("created_at","<=",date('Y-m-d H:i:s',time()))->orderBy('created_at','desc')->first();
            //$object->body_price = $prices->body_price;

            $result = array(
                'timestamp' => time(),
                'period' => $period,
                'object' => $object,
                'lines' => $lines->toArray()
            );

            return response()->json($result);
        }

    }



    public function objectsDetailUpdate(Request $request, Response $response, $id, $period)
    {
        $object = Object::find($id);//这个不取应该也没事吧
        $prices = Price::where("id_object",$id)->where("created_at","<=",date('Y-m-d H:i:s',time()))->orderBy('created_at','desc')->first();
        if ($object->body_status == 1) {
            $object['status'] = TRUE;
        } else {
            $object['status'] = FALSE;
        }

        //分时
        if($period == 1){
            $result = array(
                'timestamp' => time(),
               // 'period' => $period,
                'object' => $object,
                'lines' => $prices->toArray()
            );
            return response()->json($result);
        }else {

            $lines = Line::where('id_object', $object->id)->where('body_period', $period)->orderBy('id', 'desc')->first();


            //修改k线图的白线数据
            //由于price中有的数据 lines可能没有 造成在界面上显示不一致 所以这里不能去prices的  数据的同步已经在 fetch中实现了
            //$object->body_price = $prices->body_price;

            $result = array(
                'timestamp' => time(),
                'period' => $period,
                'object' => $object,
                'lines' => $lines->toArray()
            );
            return response()->json($result);
        }

    }

    public function ordersDetail(Request $request, Response $response, $id)
    {

        $item = Order::find($id);
        $result = array(
            'timestamp' => time(),
            'item' => $item
        );

        return response()->json($result);

    }

    public function update(Request $request, Response $response)
    {

        $result = array(
            'user' => NULL,
            'timestamp' => time(),
            'date' => date('Y-m-d'),
            'time' => date('H:i:s'),
            'objects' => array()
        );

        if ($request->input('object', null)) {
            $objects = Object::where('id', $request->input('object'))->get();
        } else {
            $objects = Object::orderBy('body_rank', 'desc')->get();
        }

        foreach ($objects as $object) {
            $result_item = $object->toArray();
            $result_item_latestPrice = Price::where('id_object', $object->id)->orderBy('created_at', 'desc')->first();

            if ($request->input('mode') == 'fs') {
                $cacheTime = time();
                if (!Cache::has('prices_' . $object->id . '_' . $cacheTime)) {
                    Cache::put('prices_' . $object->id . '_' . $cacheTime, Price::where('id_object', $object->id)->where('body_price_time', '<=', date('Y-m-d H:i:s', $cacheTime))->where('body_price_time', '>', date('Y-m-d H:i:s', strtotime($result_item_latestPrice->body_price_time) - 900))->orderBy('created_at', 'desc')->get()->toArray(), 1);
                }
                $result_item['prices'] = Cache::get('prices_' . $object->id . '_' . $cacheTime);
            } else {

                if ($object->body_tag == 'sh000010'
                    || $object->body_tag == 'sh000300'
                ) {
                    $requestString = 'http://money.finance.sina.com.cn/quotes_service/api/jsonp_v2.php/DATA/CN_MarketData.getKLineData?symbol=#CODE#&scale=5&ma=no&datalen=30';
                } else if ($object->body_tag == 'gb_$ndx') {
                    $requestString = 'http://stock.finance.sina.com.cn/usstock/api/jsonp_v2.php/DATA/US_MinKService.getMinK?symbol=.ndx&type=5';
                } else if ($object->body_tag == 'gb_$dji') {
                    $requestString = 'http://stock.finance.sina.com.cn/usstock/api/jsonp_v2.php/DATA/US_MinKService.getMinK?symbol=.dji&type=5';
                } else if ($object->body_tag == 'gb_bidu') {
                    $requestString = 'http://stock.finance.sina.com.cn/usstock/api/jsonp_v2.php/DATA/US_MinKService.getMinK?symbol=bidu&type=5';
                } else if ($object->body_tag == 'gb_baba') {
                    $requestString = 'http://stock.finance.sina.com.cn/usstock/api/jsonp_v2.php/DATA/US_MinKService.getMinK?symbol=baba&type=5';
                } else if ($object->body_tag == 'gb_jd') {
                    $requestString = 'http://stock.finance.sina.com.cn/usstock/api/jsonp_v2.php/DATA/US_MinKService.getMinK?symbol=jd&type=5';
                } else {
                    $requestString = 'http://vip.stock.finance.sina.com.cn/forex/api/jsonp.php/DATA/NewForexService.getMinKline?symbol=#CODE#&scale=5&datalen=30';
                }

                $requestString = str_replace('#CODE#', $object->body_tag, $requestString);
                $requestResult = explode('DATA(', file_get_contents($requestString));
                $requestResult = str_replace(')', '', $requestResult[1]);
                $requestResult = str_replace('{day:', '{d:', $requestResult);
                $requestResult = str_replace(',open:', ',o:', $requestResult);
                $requestResult = str_replace(',high:', ',h:', $requestResult);
                $requestResult = str_replace(',low:', ',l:', $requestResult);
                $requestResult = str_replace(',close:', ',c:', $requestResult);
                $requestResult = str_replace(',volume:', ',v:', $requestResult);
                $requestResult = str_replace('d', '"d"', $requestResult);
                $requestResult = str_replace('o', '"o"', $requestResult);
                $requestResult = str_replace('l', '"l"', $requestResult);
                $requestResult = str_replace('h', '"h"', $requestResult);
                $requestResult = str_replace('c', '"c"', $requestResult);
                $requestResult = str_replace('v', '"v"', $requestResult);
                $requestResult = str_replace(';', '', $requestResult);
                $result_item['prices'] = json_decode($requestResult, TRUE);
            }

            if ($object->body_status == 1) {
                $result_item['status'] = TRUE;
            } else {
                $result_item['status'] = FALSE;
            }

            if ($user = session('wechat.oauth_user')) {
                $user = User::where('id_wechat', $user->id)->first();
                $result_item['orders'] = Order::where('id_object', $object->id)->where('id_user', $user->id)->where('striked_at', '0000-00-00 00:00:00')->orderBy('created_at', 'desc')->get()->toArray();
            }

            $result['objects'][] = $result_item;
        }

        if ($user = session('wechat.oauth_user')) {

            $user = User::where('id_wechat', $user->id)->first();

            $latestStrikedOrder = Order::where('id_object', $object->id)->where('id_user', $user->id)->where('striked_at', '<>', '0000-00-00 00:00:00')->orderBy('created_at', 'desc')->first();
            if ($latestStrikedOrder) $latestStrikedOrder = $latestStrikedOrder->toArray();
            else $latestStrikedOrder = NULL;

            $result['user'] = array(
                'balance' => floatval($user->body_balance),
                'latestStrikedOrder' => $latestStrikedOrder
            );

        }

        return response()->json($result);

    }

    //短信验证码在这里
    // public function captchaCreate(Request $request, Response $response) {

    //     $code = mt_rand(100000, 999999);

    //     $captcha = new Captcha;
    //     $captcha->body_mobile = $request->input('mobile');
    //     $captcha->body_code = $code;
    //     $captcha->save();

         //组织短信借口地址
    //     $requestUri = env('SMS_BASE');
    //     $requestUri = str_replace('#1#', env('SMS_KEY'), $requestUri);
    //     $requestUri = str_replace('#2#', $request->input('mobile'), $requestUri);
    //     $requestUri = str_replace('#3#', urlencode("【中汇金商品交易所】你的验证码是" . $code . "，请在10分钟内输入。"), $requestUri);

    //     $result = file_get_contents($requestUri);
    //     return response()->json(['result' => $result]);

    // }


    public function captchaCreate(Request $request, Response $response)
    {

        $code = mt_rand(100000, 999999);

        $captcha = new Captcha;
        $captcha->body_mobile = $request->input('mobile');
        $captcha->body_code = $code;
        $captcha->save();

        $content = "你的验证码是" . $code . "，请在10分钟内输入。【云交易】";
        $res = $this->sendMsg($captcha->body_mobile, $content);
        if ($res) {
            return response()->json(['state' => 'ok']);
        }
        return response()->json(['state' => 'err']);

    }

    private function sendMsg($phone, $content)
    {
        $uid = env('BAMI_SMS_UID');
        $passwd = env('BAMI_SMS_PASSWD'); 
        $api = env('BAMI_SMS_API');

        $api = $api . "?";
        $api = $api . "uid=" . $uid;
        $api = $api . "&passwd=" . $passwd;
        $api = $api . "&phonelist=" . $phone;
        $api = $api . "&content=" . urlencode($content);

        $json = @json_decode(file_get_contents($api), true);
        if ($json && $json['code'] == 0) {
            return true;
        }
        return false;
    }


    public function orderCreate(Request $request, Response $response)
    {

        if (!$user = session('wechat.oauth_user')) {
            return response()->json([
                'error' => '身份验证失败，请重新打开页面再试'
            ]);
        }

        $carbon = Carbon::now();
        /*        if($carbon->hour < 9 && $carbon->hour > 4) {
                    return response()->json([
                        'error' => '非交易时间无法进行交易'
                    ]);
                }*/

        if (is_null($request->input('object', NULL))
            || is_null($request->input('stake', NULL))
            || is_null($request->input('time', NULL))
            || is_null($request->input('direction', NULL))
        ) {
            return response()->json([
                'error' => '参数提交不全，清重新打开页面再试'
            ]);
        }

        if ($request->input('stake') != 10
            && $request->input('stake') != 50
            && $request->input('stake') != 100
            && $request->input('stake') != 200
            && $request->input('stake') != 500
            && $request->input('stake') != 1000
            && $request->input('stake') != 2000
            && $request->input('stake') != 5000
            && $request->input('stake') != 10000
        ) {
            return response()->json([
                'error' => '参数提交错误，请重新打开页面再试'
            ]);
        }

        if ($request->input('time') != 60
            && $request->input('time') != 120
            && $request->input('time') != 180
            && $request->input('time') != 240
            && $request->input('time') != 300
            && $request->input('time') != 900
            && $request->input('time') != 1800
            && $request->input('time') != 3600
        ) {
            return response()->json([
                'error' => '参数提交错误，请重新打开页面再试'
            ]);
        }

        if ($request->input('direction') != 1
            && $request->input('direction') != 0
        ) {
            return response()->json([
                'error' => '参数提交错误，请重新打开页面再试'
            ]);
        }

        if (!$object = Object::find($request->input('object'))) {
            return response()->json([
                'error' => '参数提交错误，请重新打开页面再试'
            ]);
        }

        if ($object->is_disabled > 0) {
            return response()->json([
                'error' => '参数提交错误，请重新打开页面再试'
            ]);
        }

        if ((strtotime($object->updated_at) + 180) < time()) {
            return response()->json([
                'error' => '休市期间无法进行交易'
            ]);
        }

        if ($object->body_status == 0) {
            return response()->json([
                'error' => '休市期间无法进行交易'
            ]);
        }

        if (!$user = User::where('id_wechat', $user->id)->first()) {
            return response()->json([
                'error' => '身份验证失败，请重新打开页面再试'
            ]);
        }

        if (floatval($user->body_balance) < $request->input('stake')) {
            return response()->json([
                'error' => '账户可用余额不足，请先充值再交易'
            ]);
        }

        if ($user->is_disabled > 0) {
            return response()->json([
                'error' => '账户已被封禁，无法进行交易'
            ]);
        }

        DB::beginTransaction();

        //用户的余额
        $user->body_balance = floatval($user->body_balance) - $request->input('stake');
        //所有的交易总额
        $user->body_transactions = floatval($user->body_transactions) + $request->input('stake');
        $user->save();

        if ($user->body_balance < 0) {
            DB::rollback();
        } else {
            $order = new Order;
            $order->id_user = $user->id;
            $order->id_object = $object->id;
            $order->body_price_buying = $object->body_price;
            $order->body_stake = $request->input('stake');
            $order->body_bonus = $object->body_profit * $request->input('stake');
            $order->body_direction = $request->input('direction');
            $order->body_time = $request->input('time');
            $order->save();

            $record = new Record;
            $record->id_user = $user->id;
            $record->id_order = $order->id;
            $record->body_name = $request->input('direction') == 1 ? '买入看涨' : '买入看跌';
            $record->body_direction = 0;
            $record->body_stake = $order->body_stake;
            $record->save();

        }

        DB::commit();

        if (!$order) {
            return response()->json([
                'error' => '下单过于频繁，请稍后再试'
            ]);
        } else {
            //计算推荐收益
            $this->computeNetwork($user, $order);

            //按照概率调控
            if (env('ORDER_CONTROL')) {
                $this->computePrice($user, $order, $object);
            }

        }

        $result = $order->toArray();

        $order_striked_time = strtotime($order->created_at) + $order->body_time;
        $result['distance'] = intval($order->body_time);
        $result['distance_year'] = date('Y', $order_striked_time);
        $result['distance_month'] = date('m', $order_striked_time);
        $result['distance_day'] = date('d', $order_striked_time);
        $result['distance_hour'] = date('H', $order_striked_time);
        $result['distance_minute'] = date('i', $order_striked_time);
        $result['distance_second'] = date('s', $order_striked_time) + 1;

        return response()->json([
            'result' => $result
        ]);


    }

    public function payRequestUpdate(Request $request, Response $response, $id)
    {

        if (!$payRequest = PayRequest::find($id)) {
            return response()->json([
                'result' => 'FAIL'
            ]);
        }

        if ($payRequest->processed_at == '0000-00-00 00:00:00') {
            return response()->json([
                'result' => 'FAIL'
            ]);
        }

        return response()->json([
            'result' => 'OK'
        ]);

    }

    //
    public function payrequest(){
       $req = new OnlinePayRequest();
       $req->index();
    }


    //支付前端返回页面
    public function retUrl(Request $request)
    {
/*      $param = $request->all();
        $str = '';
        foreach ($param as $key => $val) {
            if ($key != 'chkValue') $str .= $val;
        }
        $sn = env('PAY_SN');
        $str .= $sn;
        if (strtolower(md5($str)) == strtolower($param['chkValue']) && ($param['transStat'] == 'S')) {
            return view("application.paySuccess",['title'=>"充值成功"]);
        } else {
            return view("application.payFailure",['title'=>"充值失败"]);
        } */
        //不做判断直接进入到成功
        return view("application.paySuccess",['title'=>"充值成功"]);
	$ReturnArray = array( // 返回字段
            "memberid" => $request->input("memberid"), // 商户ID
            "orderid" =>  $request->input("orderid"), // 订单号
            "amount" =>  $request->input("amount"), // 交易金额
            "datetime" =>  $request->input("datetime"), // 交易时间
            "returncode" => $request->input("returncode"),
        );
        $Md5key = "QgtlbbBxkn8wAcKR2O86rRTgsHUMnR";
	ksort($ReturnArray);
        reset($ReturnArray);
        $md5str = "";
        foreach ($ReturnArray as $key => $val) {
            $md5str = $md5str . $key . "=>" . $val . "&";
        }
        $sign = strtoupper(md5($md5str . "key=" . $Md5key)); 
        if ($sign == $request->input("sign")) {
            if ($request->input("returncode") == "00") {
            	   return view("application.paySuccess",['title'=>"充值成功"]);
		   //$str = "交易成功！订单号：".$_REQUEST["orderid"];
		  // exit($str);
            }else{
                   return view("application.payFailure",['title'=>"充值失败"]);
            }
        }
    }


    public function bgRetUrl(Request $request)
    {
       $param = $request->all();
       $param = json_decode(json_encode($param),true);
       
       $requestParam = json_decode($param['request'],true);
       if(intval($requestParam['statusId']) == 14){
           $order_id = $requestParam['merchantGenCode'];
           $this->pay($order_id);
           return 'SUCCESS';
       }
       
           
   
    }


    private function pay( $order_id  )
    {    
        //查看订单是否存在　还要判断时间是否为００００－００－００　００：００：００　不然的话会被处理２次
        DB::beginTransaction();
        $payRequest = PayRequest::where([["order_id",'=',$order_id],['processed_at','=','0000-00-00 00:00:00']])->lockForUpdate()->first();
        if(!$payRequest) return false;
//已经被处理过的还会再次被处理不好
        $payRequest->processed_at = date('Y-m-d H:i:s', time());
        $payRequest->save();
        DB::commit();
        //check if duplicate  这个检查很可能失败　因为加入是来了两次请求　一方面还没有存进去 第二次就开始取　可定是取不出来　所以这个操作没有百分百的>保证
        $hasRecord = Record::where('id_payRequest',$payRequest->id)->first();
        if($hasRecord) return true;

        //记录的表是加了唯一键的　如果操作不成功　则会报错　所以加钱的操作要放在记录表的后面
        $record = new Record;
        $record->id_user = $payRequest->id_user;
        $record->id_payRequest = $payRequest->id;
        $record->body_name = '帳戶充值';
        $record->body_direction = 1; 
        $record->body_stake = $payRequest->body_stake;
        $record->save(); //如果记录表这里没有保存成功　说明已经有一条记录了　就不用再增加了　加钱的动作就不要再弄了　

        $user = User::find($payRequest->id_user);
        $user->body_balance = $user->body_balance + $payRequest->body_stake;
        $user->save();

        return true;
    } 
   
}
